########################################################################
#  Searx-Qt - Lightweight desktop application for Searx.
#  Copyright (C) 2020-2024  CYBERDEViL
#
#  This file is part of Searx-Qt.
#
#  Searx-Qt is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  Searx-Qt is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
########################################################################

import os
import sysconfig  # Get path prefix (example: /usr).
import json


## Global JSON Schema container so we won't have to read a json schema file
## from disk everytime we need to verify some json data.
Schemas = {}


def json_schema_load(key, filepath):
    """! Loads an json schema into the global 'Schemas' container.

    @param key: A name to store the json schema to, existing keys will be
                overwritten!
    @type key: string
    @param filepath: Path where the json schema file is located (including
                     filename)
    @type filepath: string

    May raise an json.JSONDecodeError or UnicodeDecodeError when the schema
    json is invalid, or an OSError when it cannot access the given filepath.
    """
    with open(filepath, 'r') as f:
        data = json.load(f)

        # An exception should have been raised when open() or json.load() has
        # failed, so at this point the schema json looks valid.

        # @note: Existing keys will be overwritten/reloaded.
        Schemas.update({key: data})


def find_schema_path(schemas):
    """! Get/find path to schema json files.

     Priority:
      1. Pwd (./schema/)
      2. User (example: ~/.local/share/)
      3. Sys (example: /usr/share/)
    """
    def __path_has_schemas(path):
        for key, filename in schemas:
            full_file_path = os.path.join(path, filename)
            if (not os.path.isfile(full_file_path) or
                not os.access(full_file_path, os.R_OK)):
                return None
            return path

    def __get_config_var_schema_path(var):
        path = os.path.join(
            sysconfig.get_config_var(var),
            "share/",
            "searx-qt/schema/"
        )
        return __path_has_schemas(path)

    # Pwd path
    path = __path_has_schemas("./data/schema/")
    if path is not None:
        return path

    # User path
    path = __get_config_var_schema_path("userbase")
    if path is not None:
        return path

    # Sys path
    path = __get_config_var_schema_path("prefix")
    if path is not None:
        return path

    return None


def load_schemas():
    # Json schema files to find/use
    schemas = [
        ("searx_space_instances", "searx_space_instances.json"),
        ("searxng_config"       , "searxng_config.json"),
        ("searxng_query"        , "searxng_query.json")
    ]

    # Find path to schema files
    path = find_schema_path(schemas)
    if path is None:
        raise Exception("Could not read json schema file(s), they are either "
                        "missing or we don't have rights to read them.")

    # Load json schema files into objects
    for key, filename in schemas:
        json_schema_load(key, os.path.join(path, filename))

